package com.xstudio.pvzreborn.block.entity;

import com.xstudio.pvzreborn.block.BlockNames;
import com.xstudio.pvzreborn.handle.PVZItemStackHandler;
import com.xstudio.pvzreborn.recipe.RecipeManager;
import com.xstudio.pvzreborn.recipe.machine.polarcraftingtable.PCTRecipeBase;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

public class BlockEntityPolarCraftingTable extends PVZMachineBlockEntityBase {

	private final PVZItemStackHandler input = new PVZItemStackHandler(9, onSlotChange);
	private final LazyOptional<IItemHandler> inputCapability = LazyOptional.of(() -> input);
	private final PVZItemStackHandler output = new PVZItemStackHandler(onSlotChange);
	private final LazyOptional<IItemHandler> outputCapability = LazyOptional.of(() -> output);
	/**
	 * 上一次的配方
	 */
	private PCTRecipeBase cacheRecipe;

	public BlockEntityPolarCraftingTable(BlockPos pWorldPosition, BlockState pBlockState) {
        super(BlockEntityManager.getBlockEntityType(BlockNames.POLAR_CRAFTING_TABLE), pWorldPosition, pBlockState);
	}

	@Override
	public List<IItemHandler> getAllItemStackHandler() {
		return List.of(input, output);
	}

	@Override
	public void setRemoved() {
		super.setRemoved();
		inputCapability.invalidate();
		outputCapability.invalidate();
	}

	@Override
	protected void saveAdditional(CompoundTag pTag) {
		super.saveAdditional(pTag);
		pTag.put("input", input.serializeNBT());
		pTag.put("output", output.serializeNBT());
	}

	@Override
	public void load(@NotNull CompoundTag pTag) {
		super.load(pTag);
		this.input.deserializeNBT(pTag.getCompound("input"));
		this.output.deserializeNBT(pTag.getCompound("output"));
	}

	@NotNull
	@Override
	public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
		if (side != null && cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
			return switch (side) {
				default -> LazyOptional.empty();
				case DOWN -> outputCapability.cast();
				case UP -> inputCapability.cast();
			};
		}
		return super.getCapability(cap, side);
	}

	public float getProcess() {
		if (cacheRecipe != null && isWorking) {
			return (float) processTime / cacheRecipe.getTick();
		}
		return 0f;
	}

	public PCTRecipeBase getRecipe(List<ItemStack> inputs) {
		PCTRecipeBase result = null;
		List<PCTRecipeBase> allRecipe = RecipeManager.getRecipes(level, RecipeManager.getRecipeType(PCTRecipeBase.TYPE_ID));
		for (PCTRecipeBase recipe : allRecipe) {
			if (recipe.matches(inputs, energy.getValue())) {
				// 优先返回有序配方, 未找到再返回无序配方(如果有)
				if (!recipe.isShapeless(recipe)) {
					this.cacheRecipe = recipe;
					return recipe;
				}
				result = recipe;
			}
		}
		this.cacheRecipe = result;
		return result;
	}

	public void checkWhetherWork(List<ItemStack> inputs) {
		PCTRecipeBase recipe = (cacheRecipe != null && cacheRecipe.matches(inputs, energy.getValue())) ? cacheRecipe : getRecipe(inputs);
		if (recipe != null) {
			isWorking = output.insertItem(0, recipe.getResultItem(), true).isEmpty();
		}
	}

	public PVZItemStackHandler getInputHandler() {
		return input;
	}

	@Override
	public void tick() {
		super.tick();
		List<ItemStack> inputs = input.getAllStacks();
		checkWhetherWork(inputs);
		if (isWorking) {
			processTime++;
			if (processTime >= cacheRecipe.getTick() && energy.getValue() >= cacheRecipe.getRequireEnergy()) {
				ItemStack outStack = cacheRecipe.getResultItem().copy();
				energy.remove(cacheRecipe.getRequireEnergy());
				inputs.forEach(stack -> stack.shrink(1));
				output.insertItem(0, outStack, false);
				isWorking = false;
				processTime = 0;
			}
		} else {
			processTime = 0;
		}
	}

}
